﻿#include<iostream>
#include<string>
#include<fstream>
using namespace std;
const int reserveNum = 30;

string reserveWords[] = {
	"while","void","unsigned","typedef","switch","struct",
	"goto", "if", "int", "long", "null", "return","short",
	"signed", "sizeof", "static", "string","default",
	"do", "double", "else", "float", "for","break",
	"bool", "case", "char", "const", "continue"
};

bool scanner();
bool scannerLine(string input, ofstream& outfile, int lineNum);
bool lexAnalyzer(string character, ofstream& outfile);

bool isDigit(char ch) {
	if (ch <= '9' && ch >= '0')
		return true;
	return false;
}

bool isLetter(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')
		return true;
	return false;
}

int isReserveWord(string word) {       //判断是否是保留词
	for (int i = 0; i < reserveNum; i++) {
		if (reserveWords[i] == word)
			return i + 1;
	}
	return 0;
}

bool scanner() {
	ifstream infile;
	infile.open("test.txt");
	ofstream outfile;
	outfile.open("result.txt");
	string lineString;
	int lineNum = 1;
	while (!infile.eof()) {
		getline(infile, lineString);
		scannerLine(lineString, outfile, lineNum);
		lineNum += 1;
	}
	infile.close();
	outfile.close();
	return true;
}

bool scannerLine(string input, ofstream& outfile, int lineNum) {
	int pos = 0;
	if (input.empty())
		return true;

	char ch;
	string curChar = "";
	while (pos < input.length()) {
		ch = input[pos];
		if (ch == ' ' || ch == '\n' || ch == '\t') {
			if (curChar == "") {
				pos += 1;
				continue;
			}
			else {
				if (!lexAnalyzer(curChar, outfile)) {
					outfile << "Find Error in line：" << lineNum << endl;  //报错机制
				}
				curChar = "";
			}
		}
		else {
			curChar += ch;
		}
		pos += 1;
	}
	if (curChar != "") {
		if (!lexAnalyzer(curChar, outfile)) {
			outfile << "Find Error in line：" << lineNum << endl;
		}
		curChar = "";
	}
	return true;
}

bool lexAnalyzer(string character, ofstream& outfile) {
	int state = 0;
	int pos = 0;
	char ch;
	for (int pos = 0; pos < character.size(); pos++) {
		ch = character[pos];
		switch (state) {
		case 0:
			if (isLetter(ch)) {
				state = 1;
				break;
			}
			if (isDigit(ch)) {
				state = 2;
				break;
			}
			if (ch == '<') {
				state = 6;
				break;
			}
			if (ch == '>') {
				state = 6;
				break;
			}
			if (ch == '!') {
				state = 6;
				break;
			}
			if (ch == '=') {
				state = 6;
				break;
			}
			if (ch == '*') {
				state = 6;
				break;
			}
			if (ch == '/') {
				state = 6;
				break;
			}
			if (ch == '&') {
				state = 6;
				break;
			}
			if (ch == '|') {
				state = 6;
				break;
			}
			if (ch == '+') {
				state = 6;
				break;
			}
			if (ch == '-') {
				state = 6;
				break;
			}
			if (ch == '{') {
				state = 7;
				break;
			}
			if (ch == '}') {
				state = 7;
				break;
			}
			if (ch == '(') {
				state = 7;
				break;
			}
			if (ch == ')') {
				state = 7;
				break;
			}
			if (ch == ';') {
				state = 7;
				break;
			}
			if (ch == ',')
			{
				state = 7;
				break;
			}
			if (ch == '[') {
				state = 7;
				break;
			}
			if (ch == ']') {
				state = 7;
				break;
			}
			if (ch == '#') {
				state = 7;
				break;
			}
			if (ch == '%') {
				state = 7;
				break;
			}
			if (ch == '^') {
				state = 7;
				break;
			}
			if (ch == '\\') {
				state = 7;
				break;
			}
			if (ch == '~') {
				state = 7;
				break;
			}
			if (ch == '?') {
				state = 7;
				break;
			}
			return false;

		case 1:
			if (isLetter(ch)) {
				state = 1;
				break;
			}
			if (isDigit(ch)) {
				state = 1;
				break;
			}
			return false;

		case 2:
			if (isDigit(ch)) {
				state = 2;
				break;
			}
			if (ch == '.') {
				state = 3;
				break;
			}
			if (ch == 'E') {
				state = 8;
				break;
			}
			return false;

		case 3:
			if (isDigit(ch)) {
				state = 4;
				break;
			}
			return false;

		case 4:
			if (isDigit(ch)) {
				state = 4;
				break;
			}
			if (ch == 'E') {
				state = 8;
				break;
			}
			return false;

		case 5:
			return false;

		case 6:
			if (ch == '=') {
				state = 5;
				break;
			}
			if (ch == '+') {
				state = 5;
				break;
			}
			if (ch == '-') {
				state = 5;
				break;
			}
			if (ch == '|') {
				state = 5;
				break;
			}
			if (ch == '&') {
				state = 5;
				break;
			}
			return false;

		case 7:
			return false;

		case 8:
			if (ch == '+') {
				state = 9;
				break;
			}
			if (ch == '-') {
				state = 9;
				break;
			}
			if (isDigit(ch)) {
				state = 10;
				break;
			}
			return false;

		case 9:
			if (isDigit(ch)) {
				state = 10;
				break;
			}
			return false;

		case 10:
			if (isDigit(ch)) {
				state = 10;
				break;
			}
			return false;

		default:
			return false;
		}
	}

	switch (state) {
	case 1:
	{
		int id = isReserveWord(character);
		if (id != 0)
			outfile << character << "\t" << '<' << character << ",->\n";
		else {
			outfile << character << "\t" << '<' << "ID," << character << ">\n";
		}
	}
	break;

	case 2:
	{
		outfile << character << "\t<int," << character << ">\n";
	}
	break;

	case 4:
	{
		outfile << character << "\t<float," << character << ">\n";
	}
	break;
	case 5:
	{
		outfile << character << "\t<op," << character << ">\n";
	}
	break;
	case 6:
	{
		outfile << character << "\t<op," << character << ">\n";
	}
	break;
	case 7:
	{
		outfile << character << "\t<" << character << ",->\n";
	}
	break;
	case 10:
	{
		outfile << character << "\t<float," << character << ">\n";
	}
	break;
	default:
		return false;
	}
	return true;
}

int main() {
	scanner();
	return 0;
}
